package generator.util

import generator.entity.Row

import java.io.{FileWriter, IOException, PrintWriter}
import java.sql.{Connection, DriverManager, ResultSet, ResultSetMetaData, SQLException, SQLSyntaxErrorException, Statement}
import java.util.Date

class dataBaseConnect {

  // 数据库连接
  private val URL = "jdbc:oracle:thin:@10.1.50.204:1521:orcl"
  private var NAME = "cj1"
  private var PASS = "cj1"
  private val DRIVER = "oracle.jdbc.driver.OracleDriver"

  //    private static final String URL = "jdbc:oracle:thin:@10.1.50.204:1521:orcl";//    private static final String URL = "jdbc:oracle:thin:@10.1.50.204:1521:orcl";
  //    private static final String NAME = "cj2";//    private static final String NAME = "cj2";
  //    private static final String PASS = "cj2";//    private static final String PASS = "cj2";
  //    private static final String DRIVER = "oracle.jdbc.driver.OracleDriver";//    private static final String DRIVER = "oracle.jdbc.driver.OracleDriver";

  // 需配置项
  private val packageOutPath = "E:/program/scala/StreamTransform/src/main/java/com/entity/yx1/" // 生成实体文件所在位置


  var tableName = "" //数据库中的表名


  private val packageName = "com.entity.yx1" //实体类所在的包

  private val authorName = "gjh" // 作者名字

  private var f_util = true // 是否需要导入包java.util.*

  private var f_sql = true // 是否需要导入包java.sql.*



  private val colsPre = Array("F_NB_", "F_VC_", "F_CR_", "F_DT_")
  private var colnames: Array[String] = null // 列名数组

  private var colTypes: Array[String] = null // 列名类型数组

  private var colSizes: Array[Int] = null // 列名大小数组
  private var colNullable: Array[Boolean] = null // 列信息是否可null

  private var pkFiled: String = null //表主键

  private var con: Connection = null
  private var pStemt: Statement = null
  private var rs: ResultSet = null
  private var rsmd: ResultSetMetaData = null
  var tableInfo:Tuple2[Array[String],Array[String]] = null

  /**
   * 1、创建数据库连接
   */
  def connect(): Unit = {
    try {
      Class.forName(DRIVER)
      con = DriverManager.getConnection(URL, NAME, PASS)
      pStemt = con.createStatement.asInstanceOf[Statement]
    } catch {
      case e@(_: ClassNotFoundException | _: SQLException) =>
        e.printStackTrace()
    }
  }

  def colseConnect(): Unit = {
    try {
      if (con != null) {
        con.close()
        con = null
      }
      if (pStemt != null) {
        pStemt.close()
        pStemt = null
      }
    } catch {
      case e: SQLException =>
        e.printStackTrace()
    }
  }

  /**
   * 获取单个数据库表信息
   */
  def getTableInfo(tableName: String): Unit = {
    var size = 0
    val sql = "SELECT * FROM " + tableName
    try {
      rs = pStemt.executeQuery(sql)
      rsmd = rs.getMetaData
      size = rsmd.getColumnCount
      colnames = new Array[String](size)
      colTypes = new Array[String](size)
      colSizes = new Array[Int](size)
      colNullable = new Array[Boolean](size)
      for (i <- 0 until size) {
        colnames(i) = rsmd.getColumnName(i + 1)
        colTypes(i) = rsmd.getColumnTypeName(i + 1)
        if (colTypes(i).equalsIgnoreCase("date") || colTypes(i).equalsIgnoreCase("timestamp")) f_util = true
        if (colTypes(i).equalsIgnoreCase("blob") || colTypes(i).equalsIgnoreCase("char")) f_sql = true
        colSizes(i) = rsmd.getColumnDisplaySize(i + 1)
        colNullable(i) = rsmd.isNullable(i+1) == 1
      }
      pkFiled = getTablePk(tableName)
      //获取单张数据库表注释
//      val tableComment = getTableComment(tableName)
      //获取单张数据库表的所有列信息
//      val tempSb = getColsInfo(tableName)
      tableInfo = (colnames,colTypes)
//      //生成JavaBean文件
//      genFile(tableName, getSb(tableName, tableComment, tempSb))
    } catch {
      case e:SQLException => {
        println(s"user:${NAME} table:${tableName} ${e.getMessage}")
      }
//      case e: SQLSyntaxErrorException => {
//        if (NAME == "cqcqdb") {
//          NAME = "cj2"
//          PASS = "cj2"
//          dataBaseConnect.connect(tableName)
//          NAME = "cqcqdb"
//          PASS = "cqcqdb"
//        } else {
//          NAME = "cqcqdb"
//          PASS = "cqcqdb"
//          e.printStackTrace
//        }
//      }

    }
  }

  /**
   * 获取表主键
   *
   * @param TableName
   * @return
   */
  def getTablePk(TableName: String): String = {
    var str: String = null
    val sql = "Select  b.Column_Name pkFiled From user_Constraints a,user_Cons_Columns b　Where a.Constraint_Type = 'P' " + " and a.Constraint_Name = b.Constraint_Name And a.Owner = b.Owner And a.table_name = b.table_name And a.table_name=upper('" + TableName + "') "
    try {
      rs = pStemt.executeQuery(sql)
      while (rs.next) {
        str = rs.getString(1)
        if (null != str && str.indexOf("\r\n") != -1) str = str.replace("\r\n", "")
        if (null != str && str.indexOf("\n") != -1) str = str.replace("\n", "")
      }
    } catch {
      case e: SQLException =>
        e.printStackTrace()
    }
    str
  }



  /**
   * 获取列类型
   *
   * @param sqlType
   * @return
   */
  private def getColsType(sqlType: String): String = {
    if (sqlType.equalsIgnoreCase("binary_double")) return "double"
    else if (sqlType.equalsIgnoreCase("binary_float")) return "float"
    else if (sqlType.equalsIgnoreCase("blob")) return "byte[]"
    else if (sqlType.equalsIgnoreCase("blob")) return "byte[]"
    else if (sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase("nvarchar2") || sqlType.equalsIgnoreCase("varchar2")) return "String"
    else if (sqlType.equalsIgnoreCase("date") || sqlType.equalsIgnoreCase("timestamp") || sqlType.equalsIgnoreCase("timestamp with local time zone") || sqlType.equalsIgnoreCase("timestamp with time zone")) return "Date"
    else if (sqlType.equalsIgnoreCase("number")) return "Long"
    "String"
  }

  /**
   * 获取列名
   *
   * @param str
   * @return
   */
  private def getColsName(str: String) = {
    var tarStr = ""
    for (temp <- colsPre) {
      val preIndex = str.indexOf(temp)
      if (preIndex >= 0) {
        tarStr = str.substring(preIndex + temp.length)
        tarStr = tarStr.replace("_", "").toLowerCase
      }
    }
    tarStr
  }
}

object dataBaseConnect {
  private val db:dataBaseConnect = new dataBaseConnect()
  def findDataType(row:Row,user:String,pwd:String):String = {
    findDataType(row.cj1_tableName,row.cj1_field,user,pwd)
  }
  def findDataType(tableName:String,field:String,user:String="cj1",pwd:String="cj1"): String = {

    try {
      db.NAME = user
      db.PASS = pwd
      connect(tableName)
      if (db.tableInfo == null ) {
        return "DataTypeNotFound"
      }
      for (i <- 0 until (db.tableInfo._1.length)) {
        val colName = db.tableInfo._1(i)
        val colType = db.tableInfo._2(i)
        if (colName == field) {
          return colType
        }
      }
      "DataTypeNotFound"
    } catch {
      case s:SQLSyntaxErrorException => {
        "DataTypeNotFound"
      }
    }
  }

  def isNullable(tableName:String,fieldName:String):Boolean = {
    connect(tableName)
    for (i <- 0 until (db.tableInfo._1.length)) {
      val colName = db.tableInfo._1(i)
      if (colName.toUpperCase == fieldName.toUpperCase) {
        return db.colNullable(i)
      }
    }
    return true
  }

  def isPrimaryField(row:Row,user:String,pwd:String):Boolean = {
    isPrimaryField(row.cj1_tableName,row.cj1_field,user,pwd)
  }

  def isPrimaryField(tableName:String,field:String,user:String="cj1",pwd:String="cj1"): Boolean = {
    db.NAME=user
    db.PASS=pwd
    connect(tableName)
    db.pkFiled == field
  }
  def connect(row:Row): Unit = {
    connect(row.cj1_tableName)
  }
  def connect(tarTableName:String): Unit = {
    if (db.tableName != tarTableName) {
      db.connect()
      db.tableName = tarTableName
      db.getTableInfo(db.tableName)
      db.colseConnect()
    }
  }
  def getPrimaryField(tarTableName:String,user:String="cqcqdb",pwd:String="cqcqdb"):(String,String) = {
    db.NAME = user
    db.PASS = pwd
    connect(tarTableName)
    (db.pkFiled,findDataType(tarTableName,db.pkFiled,user,pwd))
  }

  def getPrimaryFieldCj2(tarTableName: String,user:String="sg_mis",pwd:String="sg_mis"): (String,String) = {
    db.NAME = user
    db.PASS = pwd
    connect(tarTableName)
    (db.pkFiled,findDataType(tarTableName,db.pkFiled,user,pwd))
  }
}